package com.sdry.config;

import com.sdry.realm.MyRealm;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha1Hash;

import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @version: 1.0
 * @description: shiro配置
 * @author: cb
 * @create: 2020-01-13 16:42
 **/
@Configuration
public class ShiroConfig {
    // 注入自定义的realm，告诉shiro如何获取用户信息来做登录或权限控制
    @Bean
    public Realm realm() {
        MyRealm myRealm = new MyRealm();
        return  myRealm;
    }

    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        /**
         * setUsePrefix(false)用于解决一个奇怪的bug。在引入spring aop的情况下。
         * 在@Controller注解的类的方法中加入@RequiresRole注解，会导致该方法无法映射请求，导致返回404。 加入这项配置能解决这个bug
         */
        creator.setUsePrefix(true);
        return creator;
    }

    @Bean
    public FilterRegistrationBean jwtFilter() {
        final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        JwtAuthenticationFilter filter = new JwtAuthenticationFilter();
        registrationBean.setFilter(filter);
        return registrationBean;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();
        // 访问控制
        // 可以匿名访问
        ///swagger2接口权限 开放
        chain.addPathDefinition("/swagger-ui.html", "anon");
        chain.addPathDefinition("/swagger/**", "anon");
        chain.addPathDefinition("/swagger-resources/**", "anon");
        chain.addPathDefinition("/v2/**", "anon");
        chain.addPathDefinition("/webjars/**", "anon");
        chain.addPathDefinition("/configuration/**", "anon");
        //静态资源文件
        chain.addPathDefinition("/static/**", "anon");
        //图片验证码不能拦截
        chain.addPathDefinition("/getCode", "anon");
        //app接口路径通用放行
        chain.addPathDefinition("/**/api/**", "anon");
        chain.addPathDefinition("/appLogin/toLogin", "anon");
        //404页面
        chain.addPathDefinition("/404", "anon");
        chain.addPathDefinition("/500", "anon");
        //登录不能拦截
        chain.addPathDefinition("/login", "anon");
        chain.addPathDefinition("/toLogin", "anon");
        // 其它路径均需要登录
        //其他使用注解判断
        chain.addPathDefinition("/**", "authc");
        return chain;
    }

    /**
     * shiro注解:
     *
     * @RequiresGuest 只有游客可以访问
     * @RequiresAuthentication 需要登录才能访问---->可以直接添加到类上
     * @RequiresUser 已登录的用户或“记住我”的用户能访问
     * @RequiresRoles 已登录的用户需具有指定的角色才能访问
     * @RequiresPermissions 已登录的用户需具有指定的权限才能访问
     */
    public static void main(String[] args) {//手动生成盐值和密码
        String random = new SecureRandomNumberGenerator().nextBytes().toHex();
        // 将原始密码加盐（上面生成的盐），并且用sha1算法加密1024次，将最后结果存入数据库中
        String result = new Sha1Hash("123456", random, 1024).toString();
        System.out.println("盐值:" + random);
        System.out.println("密码:" + result);
    }

}
